--[[
 -- *名称:ThreeTakeSinglePlusTypeAnalyzer
 -- *描述:三带一飞机
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-09
 -- *修改日期:2017-11-09
 ]]
local DdzSuitAnalyzer = require(basePath.."suit/ddzsuitanalyzer");
local ThreeStraightTypeAnalyzer = require(basePath.."suit/threestraight/threestraighttypeanalyzer")
local ThreeTakeSinglePlusTypeAnalyzer = pokercore.class(DdzSuitAnalyzer,false);

local FourTakeSingleAnalyzer = require(basePath .. "suit/fourtakesingle/fourtakesingletypeanalyzer") ;

local fourTakeSingleTypeAnalyzer = pokercore.new(FourTakeSingleAnalyzer);

local ThreeTypeAnalyzer = require(basePath.."suit/three/threetypeanalyzer"); --三条
local Cards = require(basePath .. "domain/cards");

ThreeTakeSinglePlusTypeAnalyzer.LIMIT_SIZE = 8 ;
ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE = 4 ;

local LIMIT_SIZE = 8;
local TUPLE_SIZE = 4;

--@Override
function ThreeTakeSinglePlusTypeAnalyzer:getSuitType()
	return DdzCardTypes.THREE_TAKE_SINGLE_PLUS;
end


--@Override
function ThreeTakeSinglePlusTypeAnalyzer:doCheckRule(cards,term,result)
	if (result:getCardNum() >= ThreeTakeSinglePlusTypeAnalyzer.LIMIT_SIZE and 
		result:getCardNum() % ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE == 0) then
		if (result:isAllCardLazi()) then -- // 全部癞子默认炸弹
			return false;
		end
		local allValues = result:getNoneLaziValueCounter():getAllValues();
		if (#allValues == 1) then --// 3*******  5555*** 默认炸弹
			return false;
		end
		local tupleNum = math.floor(result:getCardNum() / ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE); --// 分析有几组牌，三带一算做一组
		if (#allValues > (tupleNum * 4)) then 
			--// 两组的飞机有3-4个点数，三组的飞机有4-6个点数，类推 // 这里避免了 333344445555成为飞机 
			return false;
		end
		--// 遍历寻找所有可能的顺子
		for valueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 -- // 从A开始
				, PokerGameConstant.NUMBER_3_VALUE + (tupleNum - 1),-1 do
			if (DdzTypeUtil.ensureStaight(valueTemp, ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE, 
					ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) then
				if (result:getLaziCardNum() == 0) then --// 没有癞子情况下
					--// 333444555666 被认为是三顺而不是飞机
					--// 排除这种情况，主要原因是
					--// 1. 概率低
					--// 2. 显示牌型看起来比较奇怪
					--// 3. 兼容非癞子情况（非癞子的时候不出选框）
					if (result:getCardNum() == 12 and DdzTypeUtil.ensureStaight(valueTemp, ThreeStraightTypeAnalyzer.TUPLE_SIZE, 
							ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) then
						--continue;
					else 
						return true;
					end
				else 
					return true;
				end
			end
		end
		return false;
	else 
		return false;
	end
end


--@Override
function ThreeTakeSinglePlusTypeAnalyzer:doAnalysizeLaizi(cards,term,onlyMaxValue)
	local cardsResult = {};
	local result = cards:getResult();
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum() + 1, result:getCardNum());
	local tupleNum = math.floor(result:getCardNum() / ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE); --// 分析有几组牌，三带一算做一组
	--// 遍历寻找所有可能的顺子
	for  beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1  --// 从A开始
			, PokerGameConstant.NUMBER_3_VALUE + (tupleNum - 1), -1 do
		if (DdzTypeUtil.ensureStaight(beginValueTemp, ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE, 
				ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) then
			local laiziCardIndex = 0;
			local straightValues = {};
			for valueTemp = beginValueTemp, beginValueTemp - tupleNum + 1, -1 do -- // 从大到小
				result:setSortFirstValue(valueTemp);-- // 随着循环确定从哪里开始顺
				straightValues[valueTemp] = true;
				local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
				local needLaziNum = ThreeStraightTypeAnalyzer.TUPLE_SIZE - valueTempNum;
				for  i = 1,needLaziNum do
					laiziCardIndex = laiziCardIndex + 1 ;
					laiziCardList[laiziCardIndex]:changeCard(valueTemp);
				end
			end
			for i = laiziCardIndex+1, #laiziCardList do -- // 如果有剩余癞子做单张
				laiziCardList[i]:changeCard(laiziCardList[i]:getNumber());
-- //					// 这里做了一个特殊处理，玩家出牌 333444555-666 假如6是癞子，最不要生成333444555666三顺牌型
-- //					if (i < 2) {
-- //					} else {
-- //						for (int randValueTemp = PokerGameConstant.NUMBER_2_VALUE // 从2开始
-- //								; randValueTemp >= PokerGameConstant.NUMBER_3_VALUE; randValueTemp--) {
-- //							if (!straightValues.contains(randValueTemp) 
-- //									&& laiziCardList.get(i).getNumber() != DdzTypeUtil.getNumberByValue(randValueTemp)) {
-- //								((DdzCard)laiziCardList.get(i)).changeCard(randValueTemp);
-- //							}
-- //						}
-- //					}
			end
			local cardsCopy = cards:clone();
			self:analysize(cardsCopy, term);
			table.insert(cardsResult,cardsCopy:clone());
			if (onlyMaxValue) then
				break; --// 取完最大一组就跳出
			end
		end
	end
	return cardsResult;
end



--@Override
function ThreeTakeSinglePlusTypeAnalyzer:sort(cards,term)
	PokerUtil.sortCards_asc(cards);
	local result = cards:getResult();
	local cardlist = cards:getCardList();
	local sortCardList = {}--new ArrayList<Card>(result.getCardNum());
	local firstSortValue = result:getSortFirstValue();
	local tupleNum = math.floor(result:getCardNum() / ThreeTakeSinglePlusTypeAnalyzer.TUPLE_SIZE); --// 分析有几组牌，三带一算做一组
	for valueTemp = firstSortValue,  firstSortValue + tupleNum -1 do --// 把三顺排好序
		local count = 0;
		for i=#cardlist,1,-1 do
			local card = cardlist[i] ;
			if card:getValue() == valueTemp then
				table.insert(sortCardList,card);
				table.remove(cardlist,i);
				count = count + 1;
				if count == 3 then
					break; --只要三张
				end
			end
		end
	end
	for i= #sortCardList ,1 ,-1 do
		table.insert(cardlist,1,sortCardList[i]) ;
	end
	--PokerUtil.sortCards_asc(cards);
end



--@Override
function ThreeTakeSinglePlusTypeAnalyzer:containsPossibleCards(handCards,term) 
	local result = handCards:getResult();
	if (result:getCardNum() < LIMIT_SIZE) then -- // 张数不够
		return false;
	end
	--// 遍历寻找所有可能的顺子
	for beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 --// 从A开始
			, PokerGameConstant.NUMBER_3_VALUE + LIMIT_SIZE / TUPLE_SIZE - 1,-1 do
		if (DdzTypeUtil.ensureTupleStaightDesc(
				beginValueTemp, LIMIT_SIZE / TUPLE_SIZE, ThreeTypeAnalyzer.TUPLE_SIZE, handCards, term, result)) then -- // 最低标准顺一下
			return true;
		end
	end
	return false;
end

--/** 最多使用癞子的数量 */
local MAX_USE_LAIZI_CARD_NUM = 8;

--/** 防重复判定的比例值 参照 int key = tupleNum * TUPLE_WEIGHT + beginValueTemp; */
local TUPLE_WEIGHT = 1000000;

--/** 癞子权重，区分癞子变成的5 和 原本就是5 */
local LAIZI_WEIGHT = 1000;

--@Override
function ThreeTakeSinglePlusTypeAnalyzer:doListPossibleCards(handCards, term)
	local cardsResult = {};
	--// 非癞子部分
	local result = handCards:getResult();
	local noneLaiziCardList = handCards:subList(1, result:getNoneCardNum());
	local noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
	noneLaiziCards:setResult(handCards:getResult():clone());
	local noneLaiziCardsResult = noneLaiziCards:getResult();
	noneLaiziCardsResult:collectNumber(noneLaiziCards, term);
	--// 癞子部分
	local laiziCardList = handCards:subList(result:getNoneCardNum()+1, result:getCardNum());
	local laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
	laiziCards:setResult(handCards:getResult():clone());
	
	local laiziCardNum = result:getLaziCardNum();
	local maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum and MAX_USE_LAIZI_CARD_NUM or laiziCardNum;
	local exsitKeys = {} ;

	for useLaiziCardNum = 0,maxUseLaiziCardNum do --// 补几张癞子
		--// 从5顺开始找 10.JQK1 找完找 9.10.J.Q.K.1 在找 8.9.10.J.Q.K.1 
		for tupleNum = LIMIT_SIZE / TUPLE_SIZE
				,(noneLaiziCardsResult:getCardNum() + useLaiziCardNum) / TUPLE_SIZE do
			local partLenResult = {} ;-- // 部分长度的结果 
			--// 遍历寻找所有可能的顺子  10.J.Q.K.1 找完找 9.10.J.Q.K 在找 8.9.10.J.Q
			for beginValueTemp = PokerGameConstant.NUMBER_2_VALUE - 1 --// 从A开始
					,PokerGameConstant.NUMBER_3_VALUE + tupleNum - 1,-1 do
				local modelCardsCopy = noneLaiziCards:clone(); --// 常规牌副本
				local modelResultCopy = modelCardsCopy:getResult();
				local useLaiziCardsCopy = DdzTypeUtil.cloneSublistedCards(laiziCards, 1, useLaiziCardNum); -- 癞子副本
				table.reverse(useLaiziCardsCopy); --// 因为这里是倒序赋值，避免 把点数小的癞子牌赋成大值又把点数大的癞子牌赋成小值 的疑惑
				local checkCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardsCopy); --// 常规牌补上癞子，用于校验顺子
				local checkResult = checkCards:getResult();
				checkResult:collectNumber(checkCards, term); --// 收集下信息
				local straightKey = tupleNum * TUPLE_WEIGHT + beginValueTemp;
				if ( not exsitKeys[straightKey] -- // 每种顺子仅判定一次
						and DdzTypeUtil.ensureTupleStaightDesc(beginValueTemp, tupleNum, ThreeTypeAnalyzer.TUPLE_SIZE, checkCards, term, checkResult)) then
					exsitKeys[straightKey] = true ;
					local tupleCards = pokercore.new(Cards);
					local firstSortValue = -1;
					for valueTemp = beginValueTemp,beginValueTemp - tupleNum+ 1,-1 do -- // 从大到小
						firstSortValue = valueTemp;
						local valueTempNum = modelResultCopy:getNoneLaziValueCounter():getValueCount(valueTemp);
						if (valueTempNum >= ThreeTypeAnalyzer.TUPLE_SIZE) then
							local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, ThreeTypeAnalyzer.TUPLE_SIZE);
							tupleCards:addCards(removedCardList);
						else
							local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
							local needLaiziCardNum = ThreeTypeAnalyzer.TUPLE_SIZE - valueTempNum;
							for i = 1,needLaiziCardNum do --// 用了癞子才加上，不会任意补全（癞子不会去替代玩家已有的顺子中的元素）
								local laiziCardCopy = table.remove(useLaiziCardsCopy,1);
								laiziCardCopy:changeCard(valueTemp);
								table.insert(removedCardList,laiziCardCopy);
							end
							tupleCards:addCards(removedCardList);
						end
					end
					--// 是否所有头部顺子都是癞子 ******带56，去重
					local isAllTupleCardLaiz = true;
					for _,tupleCard in ipairs(tupleCards) do
						if (not tupleCard:isLazi()) then
							isAllTupleCardLaiz = false;
						end
					end
					local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardsCopy);
					--dump(remainCards,"ThreeTakeSinglePlusTypeAnalyzer:doListPossibleCards remainCards");
					--// 寻找相应的几张单牌
					local takenCardsList = fourTakeSingleTypeAnalyzer:repeatSelectSingleCards(remainCards, tupleNum, term);
					local subPartLenResult = {}; -- // 部分长度的结果 
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						local resultKey = tupleNum * TUPLE_WEIGHT;
						if (isAllTupleCardLaiz) then
							resultKey = resultKey + TUPLE_WEIGHT * 4; --// 这里随便给个值表示头部全是癞子 
							for _,card in ipairs(takenCards.cardList) do
								if (card:isLazi()) then -- // 癞子权重，区分癞子变成的5 和 原本就是5
									resultKey = resultKey + card:getValue() * LAIZI_WEIGHT;
								else 
									resultKey = resultKey + card:getValue();
								end
							end
						else 
							for _,card in ipairs(resultCards.cardList) do
								if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
									resultKey = resultKey + card.getValue() * LAIZI_WEIGHT;
								else 
									resultKey = resultKey + card.getValue();
								end
							end
						end
						if (not exsitKeys[resultKey] 
								and self:match(resultCards, term)) then
							exsitKeys[resultKey] = true;
							--// 保证排序
							resultCards:getResult():setSortFirstValue(firstSortValue);
							self:analysize(resultCards, term);
							table.insert(subPartLenResult,resultCards);
						end
					end
					--partLenResult.addAll(0, subPartLenResult); // 这里要逆序保证小的在前面
					for i = #subPartLenResult,1,-1 do
						table.insert(partLenResult,1,subPartLenResult[i]);
					end
				end
			end
			--cardsResult.addAll(partLenResult);
			table.addAll(cardsResult,partLenResult);
		end
	end
	return cardsResult;
end





return ThreeTakeSinglePlusTypeAnalyzer;

